package com.example.easyscript.service.master;

import cn.hutool.extra.cglib.CglibUtil;
import com.example.easyscript.bean.StepHandler;
import com.example.easyscript.bean.task.*;
import com.example.easyscript.dto.Resp.RunnerInfoReq;
import com.example.easyscript.enums.OperationStatusEnum;
import com.example.easyscript.enums.StepTypeEnum;
import com.example.easyscript.enums.TaskStatusEnum;
import com.example.easyscript.service.SystemImageServive;
import com.example.easyscript.service.master.intf.StepHandlerService;
import com.example.easyscript.service.master.intf.TaskRunnerService;
import com.example.easyscript.utils.JnaUtils;
import com.example.easyscript.utils.SpringContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 任务执行器
 */
@Service
public class TaskRunnerServiceImpl implements TaskRunnerService {

    @Resource
    private SystemImageServive systemImageServive;

    @Resource
    private StepHandlerService stepHandlerService;

    //当前的任务
    private TaskBean currentTaskBean;
    //状态图
    private StateDiagram stateDiagram;
    //状态集
    private Map<Integer, StatusBean> stateBeanMap;


    /**
     * 加载当前任务
     *
     * @param taskBean 任务
     */
    @Override
    public void loadTaskBean(TaskBean taskBean) {
        this.currentTaskBean = taskBean;
        this.stateDiagram = taskBean.getStateDiagram();
        this.stateBeanMap = stateDiagram.getStateBeanMap();
    }

    @Override
    public RunnerInfoReq getRunnerInfo() {
        return new RunnerInfoReq(currentTaskBean);
    }

    /**
     * 执行任务
     *
     * @param taskBean 任务
     */
    @Override
    public void performTask(TaskBean taskBean) {
        //加载当前任务
        loadTaskBean(taskBean);
        //判断当前目标状态是否以丢失
        TaskStatusEnum status = taskBean.getStatus();
        //解析当前任务将要做什么预处理取出要进行的操作
        analysisTask(taskBean);
        JnaUtils.setTop(taskBean.getWindowsName());
        if (!status.equals(TaskStatusEnum.TERMINAL)) {
            if (!status.equals(TaskStatusEnum.MISS_STATES)) {
                //目标状态没有丢失判断当前状态是否是目标状态
                verifyCurrentStateAndExecuteTask();
            } else {
                //当前任务丢失状态则要确定当前状态
                determineCurrentStatusAndCalibrate();
            }
        } else {
            System.out.println("任务" + taskBean.getTaskName() + "所有操作已经完成");
        }
        System.out.println("----------------------------运行结束--------------------------------");
    }

    /**
     * 分析判断下一个操作集要改怎么处理
     */
    public void analysisTask(TaskBean taskBean) {
        if (taskBean.getCurrentOperationBean() == null) {
            //如果当前操作集为空则从操作队列之中拿出来
            LinkedList<OperationBean> que = taskBean.getOperationQue();
            if (que.size() > 0) {
                OperationBean operationBean = que.pop();
                //加载一个新的进到里面去
                taskBean.setCurrentOperationBean(operationBean);
                //设置目标状态
                taskBean.setTargetStateSeq(operationBean.getStartStatus());
                taskBean.setTargetStepSeq(0);
                operationBean.setStatusEnum(OperationStatusEnum.running);
            } else {
                taskBean.setStatus(TaskStatusEnum.TERMINAL);
            }
        }
    }

    /**
     * 确认当前状态是否是目标状态并且执行任务
     */
    @Override
    public void verifyCurrentStateAndExecuteTask() {
        //判断当前状态是否与实际状态相同
        if (checkCurrentStatusIsFactStatus()) {
            if (checkCurrentStatusIsTargetStatus()) {
                //当前的状态与目标状态一致则可以执行步骤
                handleStep();
            } else {
                //从当前状态转移到目标状态
                toTargetStatus();
            }
        } else {
            //目标状态与当前状态不一致则确认当前状态
            determineCurrentStatusAndCalibrate();
        }
    }

    //从当前状态转移到目标状态
    //进入这个函数的前提是已经确定好当前状态 ， 并且与目标状态不一致时才会进入到这个函数
    private void toTargetStatus() {
        //1.先获取当前的状态
        StatusBean currentStateBean = stateBeanMap.get(currentTaskBean.getCurrentStateSeq());
        StatusBean targetStatusBean = stateBeanMap.get(currentTaskBean.getTargetStateSeq());
        System.out.println("尝试纠正偏离的轨道 从 《" + currentStateBean.getStatusName() + "》 到 《" + targetStatusBean.getStatusName() + "》");
        EntranceBean entrance = stateDiagram.getNextStep(currentStateBean.getOrderId(), targetStatusBean.getOrderId());
        if (entrance == null) {
            //找不到合适的路径从当前的状态转移到目标状态，无解
            //todo 装载错误记录系统
            throw new RuntimeException("错误的路径转移");
        }
        //找到合适的路径进行状态转移,新建一个系统步骤
        StepBean moveBean = new StepBean(entrance);
        boolean success = stepHandlerService.executionStep(moveBean, currentTaskBean);
        if (success) {
            currentTaskBean.setCurrentStateSeq(entrance.getEndStatusId());
            //当前状态已经纠正
            System.out.println("当前状态已经纠正为： " + stateBeanMap.get(entrance.getEndStatusId()).getStatusName());
        } else {
            currentTaskBean.executionFailed();
            throw new RuntimeException("状态转移失败");
        }
    }

    //判断当前状态与实际状态是否相同
    private boolean checkCurrentStatusIsFactStatus() {
        System.out.println("正在判断当前状态与实际状态是否相同");
        StatusBean currentStatusBean = stateBeanMap.get(currentTaskBean.getCurrentStateSeq());
        return checkStatusIsCapture(currentStatusBean);
    }

    /**
     * 执行步骤
     */
    @Override
    public void handleStep() {
        OperationBean operationBean = currentTaskBean.getCurrentOperationBean();
        int nextSept = currentTaskBean.getTargetStepSeq() + 1;
        if (operationBean.getStepSize() >= nextSept) {
            // 下一步还有步骤没有完成执行下一步
            Map<Integer, StepBean> stepBeanMap = operationBean.getStepBeanMap();
            StepBean stepBean = stepBeanMap.get(nextSept);
            System.out.println("正在执行步骤 " + stepBean.getStepName());
            boolean success = stepHandlerService.executionStep(stepBean, currentTaskBean);
            if (success) {
                //修改当前状态
                currentTaskBean.setCurrentStateSeq(stepBean.getStatusId());
                //修改目标状态
                currentTaskBean.setTargetStateSeq(stepBean.getStatusId());
                //修改目标步骤
                currentTaskBean.setTargetStepSeq(nextSept);
                //如果执行成功 任务结束
                currentTaskBean.setWaitTime(stepBean.getWaitTime());
                currentTaskBean.setEndTime(System.currentTimeMillis());
                currentTaskBean.executionSuccess();
                System.out.println("步骤执行成功预期到达状态为：" + stateBeanMap.get(stepBean.getStatusId()).getStatusName());
            } else {
                System.out.println("步骤执行失败！！！");
                // 任务执行失败累计 1
                currentTaskBean.executionFailed();
            }
        } else {
            // 切换操作
            System.out.println("当前操作以完成准备切换操作");
            changeOperation(currentTaskBean);
            currentTaskBean.executionSuccess();
        }
    }


    /**
     * 判断实际状态是否与实际对应上
     */
    @Override
    public boolean checkCurrentStatusIsTargetStatus() {
        System.out.println("判断实际状态是否与目标状态对应上");
        System.out.println(currentTaskBean.getCurrentStateSeq().equals(currentTaskBean.getTargetStateSeq()) ? "实际状态与目标状态相符！" : "ERROR 实际状态与目标状态不相符！");
        return currentTaskBean.getCurrentStateSeq().equals(currentTaskBean.getTargetStateSeq());
    }

    private boolean checkStatusIsCapture(StatusBean stateBean) {
        //获取对应状态的所有标识
        List<String> signUrls = stateBean.getSignsUrl();
        //遍历所有的标识 判断所有的标识是否在当前截图中
        String captureUrl = systemImageServive.getTaskCurrentCapture(currentTaskBean);
        int passCount = systemImageServive.checkTemplateIsInSource(signUrls, captureUrl);
        System.out.println(passCount == signUrls.size() ? "相符" : "不相符！");
        return passCount == signUrls.size();
    }

    /**
     * 切换操作
     */
    @Override
    public void changeOperation(TaskBean taskBean) {
        taskBean.setCurrentOperationBean(null);
    }

    /**
     * 确认实际状态是什么并且进行状态校准
     */
    @Override
    public void determineCurrentStatusAndCalibrate() {
        //尝试去确定当前状态
        if (!determineCurrentStatus()) {
            //状态确定不成功则任务执行失败
            currentTaskBean.executionFailed();
        }
    }

    //确定当前的状态
    private boolean determineCurrentStatus() {
        //获取当前的截图
        String source = systemImageServive.getTaskCurrentCapture(currentTaskBean);
        //遍历状态集确定当前状态
        Collection<StatusBean> stateBeanList = stateBeanMap.values();
        for (StatusBean stateBean : stateBeanList) {
            System.out.println("正在验证" + stateBean.getStatusName());
            int passCount = systemImageServive.checkTemplateIsInSource(stateBean.getSignsUrl(), source);
            if (passCount > 0 && passCount == stateBean.getSignsUrl().size()) {
                //所有标识点都在确定状态，找到当前的目标状态
                currentTaskBean.setStatus(TaskStatusEnum.NORMAL_STATES);
                //修正当前状态
                currentTaskBean.setCurrentStateSeq(stateBean.getOrderId());
                currentTaskBean.executionSuccess();
                System.out.println("确定当前页面是  《" + stateBean.getStatusName() + "》");
                return true;
            }
        }
        System.out.println("找不到对应页面");
        //确定状态失败
        return false;
    }

}